package top.ucat.x.file.service;


import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;import org.springframework.beans.factory.annotation.Autowired;
import top.ucat.box.cloud.common.exception.BaseException;
import top.ucat.box.starter.mybatis.plus.base.service.BaseCrudServiceImpl;
import top.ucat.x.file.beans.*;
import top.ucat.x.file.util.AliossUtil;
import top.ucat.x.system.dao.api.SysAliOssDao;
import top.ucat.x.system.dao.api.SysFileDao;
import top.ucat.x.system.entity.SysAliOss;
import top.ucat.x.system.entity.SysFile;
import top.ucat.x.system.service.provider.AliOssService;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Jun
 * @since 2019-06-19
 */
@Service
public class FileServiceImpl extends BaseCrudServiceImpl<SysFile> implements FileService {


    @Autowired
    private SysAliOssDao sysAliOssDao;

    @Autowired
    private SysFileDao sysFileDao;

    @Reference
    private AliOssService aliOssService;


    @Override
    public AliStsVo getAliOssTstToken(String module, String userId) {
        SysAliOss alioss = aliOssService.getUseringOssConfiguration();
        AliStsVo stsToken = AliossUtil.getStsToken(alioss, module, userId);
        return stsToken;
    }

    public AliStsVo getAliOssTstToken(String module) {

        ProtocolType protocolType = ProtocolType.HTTPS;
        String accessKeyId = "LTAIcVG7nuyxTdCE";
        String accessKeySecret = "ldwfZMq3y36929CWAmQ6G0k99s0Hka";

        String roleArn = "acs:ram::1107431920952250:role/aliyunosstokengeneratorrole";
        String roleSessionName = "external-username";
        String policy = "{\n" +
                "  \"Statement\": [\n" +
                "    {\n" +
                "      \"Action\": [\n" +
                "        \"oss:*\"\n" +
                "      ],\n" +
                "      \"Effect\": \"Allow\",\n" +
                "      \"Resource\": [\"acs:oss:*:*:*\"]\n" +
                "    }\n" +
                "  ],\n" +
                "  \"Version\": \"1\"\n" +
                "}\n";

        long durationSeconds = 3600;
//        String STS_API_VERSION = "2016-08-01";
        String STS_API_VERSION = "2015-04-01";
        String REGION_CN_HANGZHOU = "cn-shenzhen";

        IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);

        // 创建一个 AssumeRoleRequest 并设置请求参数
        final AssumeRoleRequest request = new AssumeRoleRequest();
        request.setVersion(STS_API_VERSION);
        request.setMethod(MethodType.POST);
        request.setProtocol(protocolType);
        request.setRoleArn(roleArn);
        request.setRoleSessionName(roleSessionName);
        request.setPolicy(policy);
        request.setDurationSeconds(durationSeconds);

        // 发起请求，并得到response
        final AssumeRoleResponse response;
        try {
            response = client.getAcsResponse(request);
            AssumeRoleResponse.Credentials credentials = response.getCredentials();
            AliStsVo aliStsVo = AliStsVo.builder().accessKeyId(credentials.getAccessKeyId()).
                    accessKeySecret(credentials.getAccessKeySecret()).
                    securityToken(credentials.getSecurityToken()).
                    expiration(credentials.getExpiration()).build();
            return aliStsVo;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public AliOssSiguatureVo getAliOssSignature(String userId, String module) {

        //        String endpoint = "oss-cn-shenzhen.aliyuncs.com";
//        String accessKeyId = "LTAIeLU7UG4wvks1";
//        String accessKeySecret = "H8iaAZsimN6Nwy0O6suvYMYPINTqAP";

        //todo 待完善 阿里签名
        SysAliOss alioss = aliOssService.getUseringOssConfiguration();
//        String endpoint = alioss.getOutDomain().substring(alioss.getOutDomain().indexOf("//") + 2, alioss.getOutDomain().length() - 1);
        String endpoint = "";
        SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
        String dir = module + "/" + userId + sdf.format(new Date());
        long expireTime = 600;


        //过期时间
        Date date = new Date();
        long sysTime = System.currentTimeMillis();
        long expireEndTime = sysTime + expireTime * 1000;
        Date expiration = new Date(expireEndTime);


        //条件限制
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);


        OSSClient client = new OSSClient(endpoint, new DefaultCredentialProvider(alioss.getAppKey(), alioss.getAppSecret()), null);
        String postPolicy = client.generatePostPolicy(expiration, policyConds);
        byte[] binaryData = new byte[0];
        try {
            binaryData = postPolicy.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new BaseException("权限转换出错", 500);
        }
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);

        //计算出签名
        String postSignature = client.calculatePostSignature(postPolicy);

        //返回签名等参数
        AliOssSiguatureVo siguatureVo = AliOssSiguatureVo.builder().
                accessKey(alioss.getAppKey()).
                policy(encodedPolicy).
                signature(postSignature).
                dir(dir).
                host(alioss.getBucketDomain()).
                expire(expireEndTime).
                sysTime(sysTime).
                accessDomain(alioss.getAccessDomain()).build();

        return siguatureVo;
    }

    @Override
    public FileVo checkFileByMd5(String md5) {
        QueryWrapper<SysFile> wrapper = this.sysFileDao.getWrapper();
        wrapper.eq("md5", md5);
        List<SysFile> list = this.sysFileDao.list(wrapper);
        if (list != null && list.size() > 0) {
            FileVo fileVo = new FileVo();
            BeanUtils.copyProperties(list.get(0), fileVo);
            return fileVo;
        }
        return null;
    }

    @Override
    public AliMobileStsVo getAliMobileSts(String module, String userId) {
        AliStsVo vo = this.getAliOssTstToken(module, userId);
        AliMobileStsVo stsVo = AliMobileStsVo.builder()
                .StatusCode("200")
                .AccessKeyId(vo.getAccessKeyId())
                .AccessKeySecret(vo.getAccessKeySecret())
                .Expiration(vo.getExpiration())
                .SecurityToken(vo.getSecurityToken())
                .build();
        return stsVo;
    }

    @Override
    public AliMobileDetailVo getMobileDetail(String module, String userId) {
        SysAliOss alioss = aliOssService.getUseringOssConfiguration();
        String fileStoreDir = AliossUtil.getFileStoreDir(module, userId);
        AliMobileDetailVo vo = AliMobileDetailVo.builder()
                .accessDomain(alioss.getAccessDomain())
                .endpoint(alioss.getEndpoint())
                .region(alioss.getRegion())
                .bucketName(alioss.getBucketName())
                .stsServerUrl(alioss.getStsServerUrl())
                .folderPath(fileStoreDir)
                .build();
        return vo;
    }
}
